home *** CD-ROM | disk | FTP | other *** search
- # /***********************************************************
- # Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
- # Amsterdam, The Netherlands.
- #
- # All Rights Reserved
- #
- # Permission to use, copy, modify, and distribute this software and its
- # documentation for any purpose and without fee is hereby granted,
- # provided that the above copyright notice appear in all copies and that
- # both that copyright notice and this permission notice appear in
- # supporting documentation, and that the names of Stichting Mathematisch
- # Centrum or CWI not be used in advertising or publicity pertaining to
- # distribution of the software without specific, written prior permission.
- #
- # STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
- # THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- # FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
- # FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
- # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- #
- # ******************************************************************/
-
- # Continuously check radio transmissions on one or more ports.
- # After an idea of Behr de Ruiter.
- #
- # usage: checkradio [-t] [port] ...
- #
- # Ports are given as command line arguments, default is radio's default.
- # Shorthands 1..99 can be used as for radio's -p argument.
- #
- # With the -t option, repeatedly print status for each port argument.
- # Without -t, pop up a GL window displaying the CD file if there is noise.
-
- # For best results, use /ufs/guido/bin/sgi/python to execute this.
- # Don't make the file executable; then dynamic loading of audioop fails!
-
- # XXX To do:
- # - need an option to suppress looping when using -t
- # - need a `status only' option that sets exit status only
- # - DELAY and LOOP should be under control of command line options
- # - add options to specify font, colors and so on
- # - optionally tune radio to the first station transmitting noise
- # - should listen to info packets instead
- # - move the symbolic constants and some subroutines to separate modules
-
-
- import sys
- import socket
- import audioop
- import string
- import time
- import os
- from stat import *
- from SOCKET import *
- import getopt
-
-
- # Parametrizations
-
- CTL_PORT = 54319 # control port
- PORT_OFFSET = 54320 # port offset if 1 <= port <= 99
- DEF_PORT = 54321 # default port (if no args)
- LOOP = 15 # listen for this many tenths seconds
- DELAY = 10 # seconds between successive tries
- LIMIT = 256 # silence threshold
- BUFSIZE = 1500 # read buffer size
-
-
- # Status constants returned by checkport()
-
- TUNED = 'already tuned in'
- BINDFAILURE = 'bind failure'
- DEAD = 'not transmitting'
- SILENT = 'transmitting silence'
- NOISY = 'transmitting'
-
-
- # Main program
-
- def main():
- try:
- optlist, args = getopt.getopt(sys.argv[1:], 'tx:y:')
- except getopt.error:
- sys.stdout = sys.stderr
- print 'usage: checkradio',
- print '[-x xorg] [-y yorg] [-t] [port] ...'
- print '-x xorg, -y yorg: left top origin of window',
- print '(negative values: right bottom)'
- print '-t: tty mode output (looping), no window'
- sys.exit(2)
- #
- do_win = 1
- x, y = 140, 4
- for opt, arg in optlist:
- if opt == '-t':
- do_win = 0
- elif opt == '-x':
- x = int(eval(arg))
- elif opt == '-y':
- y = int(eval(arg))
- #
- ports = []
- for arg in args:
- p = int(eval(arg))
- if 1 <= p <= 99:
- p = p + PORT_OFFSET
- ports.append(p)
- if not ports:
- ports.append(DEF_PORT)
- #
- if do_win:
- wincode(ports, (x, y))
- else:
- ttycode(ports)
-
-
- # Code for tty version
-
- def ttycode(ports):
- while 1:
- for p in ports:
- print 'port', p, ':',
- sys.stdout.flush()
- status, sender = checkport(p)
- if status in (NOISY, SILENT):
- cdname = getinfostring(p, sender)
- if cdname:
- status = status + ': ' + cdname
- print status
- time.sleep(DELAY)
-
- def getinfostring(port, sender):
- name, port, transmitting, logfile, age, contents = \
- getinfo(port, sender)
- if 0 <= age < 99999:
- contents = contents + ' (' + formatage(age) + ')'
- return contents
-
- def formatage(age):
- if age < 60: return `age` + ' sec'
- if age < 3600: return `age/60` + ' min'
- if age < 24*3600: return `age/3600` + ' hrs'
- return `age/(24*3600)` + ' days'
-
-
- # Code for GL window version
-
- # Parameters
- timer_rate = 60 # Seconds
- color_choices = [95, 94, 93, 92, 91, 90, 89, 88]
-
- def wincode(ports, org):
- if len(ports) > 1:
- sys.stderr.write('warning: only the first port arg is used\n')
- port = ports[0]
- import gl, GL, DEVICE, fm
- #gl.foreground()
- fh = fm.findfont('Helvetica').scalefont(8)
- fh.setfont()
- str, age = getinfopair(port)
- # Always create the window initially -- to initialize gl
- wid = createwin(org, fh, str)
- gl.qdevice(DEVICE.TIMER1)
- gl.noise(DEVICE.TIMER1, timer_rate*60) # 60th of a second
- while 1:
- dev, val = gl.qread()
- if dev == DEVICE.REDRAW:
- redraw_window(wid, str, age)
- elif dev == DEVICE.TIMER1:
- oldstr = str
- str, age = getinfopair(port)
- if str <> oldstr:
- if wid > 0:
- org = currentorg(org)
- deletewin(wid)
- wid = -1
- if str:
- wid = createwin(org, fh, str)
- elif wid > 0:
- redraw_window(wid, str, age)
-
- def currentorg((oldx, oldy)):
- import gl, GL
- x, y = gl.getorigin()
- if oldx >= 0 and oldy >= 0: return (oldx, oldy)
- xsize, ysize = gl.getsize()
- xmax = gl.getgdesc(GL.GD_XPMAX)
- ymax = gl.getgdesc(GL.GD_YPMAX)
- if oldx < 0:
- x = (x + xsize) - (xmax+1)
- if x >= 0: x = -1
- if oldy < 0:
- y = (y + ysize) - (ymax+1)
- if y >= 0: y = -1
- return x, y
-
- def redraw_window(wid, str, age):
- import gl, GL, fm
- mins = age/60 # Convert to minutes
-
- gl.color(color_choices[min(max(0, mins/9), len(color_choices)-1)])
- gl.clear()
-
- gl.color(GL.BLACK)
-
- xsize, ysize = gl.getsize()
- gl.bgnclosedline()
- gl.v2i(0, 0)
- gl.v2i(0, ysize-1)
- gl.v2i(xsize-1, ysize-1)
- gl.v2i(xsize-1, 0)
- gl.endclosedline()
-
- gl.cmov2i(4, 4)
- fm.prstr(str)
-
- def createwin((x, y), fh, str):
- import gl, GL, DEVICE
- gl.noborder()
- xsize = fh.getstrwidth(str) + 7
- ysize = 16
- if x < 0 or y < 0:
- xmax = gl.getgdesc(GL.GD_XPMAX)
- ymax = gl.getgdesc(GL.GD_YPMAX)
- if x < 0: x = x + (xmax+1) - xsize
- if y < 0: y = y + (ymax+1) - ysize
- gl.prefposition(x, x + xsize, y, y + ysize)
- wid = gl.winopen('checkradio')
- gl.qenter(DEVICE.REDRAW, wid)
- return wid
-
- def deletewin(wid):
- import gl, GL, DEVICE
- gl.winclose(wid)
-
- def getinfopair(port):
- state, sender = checkport(port)
- if state not in (NOISY, SILENT):
- return '', 99999
- name, port, transmitting, logfile, age, contents = \
- getinfo(port, sender)
- return contents, age
-
-
- # Common code
-
- def checkport(port):
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- try:
- s.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
- except socket.error:
- print 'warning: cannot set socket option SO_REUSEPORT'
- try:
- s.bind('', port)
- except socket.error, msg:
- if msg == (114, 'Address already in use'):
- return TUNED, msg
- else:
- return BINDFAILURE, msg
- transmitting = 0
- noise = 0
- sender = None
- for i in range(LOOP):
- if i: time.millisleep(100)
- while s.avail():
- data, sender = s.recvfrom(BUFSIZE)
- if data[:6] == 'radio:': continue
- transmitting = 1
- lindata = audioop.ulaw2lin(data, 2)
- n = audioop.max(lindata, 2)
- if n > LIMIT:
- noise = n
- break
- if noise: break
- s.close()
- if not transmitting:
- return DEAD, sender
- if not noise:
- return SILENT, sender
- return NOISY, sender
-
- def getinfo(port, sender):
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- s.sendto('radio:s', (sender[0], CTL_PORT))
- for i in range(LOOP):
- time.millisleep(100)
- while s.avail():
- data, realsender = s.recvfrom(BUFSIZE)
- if data[:7] == 'radio:S':
- return decodeinfo(data)
-
- def decodeinfo(data):
- fields = string.splitfields(data, ':')
- name = fields[2]
- port = eval(fields[3])
- if fields[4:]:
- transmitting = eval(fields[4])
- logfile = fields[5]
- age = eval(fields[6])
- contents = string.joinfields(fields[7:], ':')
- else:
- transmitting = -1
- programfile = '/ufs/' + name + '/CD'
- logfile = programfile + 'log'
- age = getage(programfile)
- if age == None:
- age = -1
- contents = getcontents(programfile)
- if contents == None:
- contents = '???'
- return name, port, transmitting, logfile, age, contents
- return None
-
- def getcontents(filename):
- try:
- f = open(filename, 'r')
- except IOError:
- return None
- res = f.readline()
- f.close()
- return string.strip(res)
-
- def getage(filename):
- try:
- st = os.stat(filename)
- except os.error:
- return None
- return time.time() - st[ST_MTIME]
-
-
- # Call the main program
-
- try:
- main()
- except KeyboardInterrupt:
- print
- print '[Interrupt]'
-